package org.enwey.icarenew.API;

import android.util.Log;

import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Map;

/**
 * Created by enwey on 1/21/2015.
 */
public class RequestAction<T> extends Request<T> {
    private String TAG = "RequestAction";
    private Class<T> clazz;
    private Response.Listener<T> successListener = null;
    private final LinkedList<RequestParam> requestParams = new LinkedList<RequestParam>();
    private String url;
    int httpMethod;
    private Type type;
    private RequestBody requestBody;

    public RequestAction(int httpMethod, String url, Class<T> clazz, Type type, RequestBody body, Response.ErrorListener errorListener, Response.Listener<T> successListener) {
        super(httpMethod, url, errorListener);
        this.url = url;
        this.httpMethod = httpMethod;
        this.clazz = clazz;
        this.requestBody = body;
        this.type = type;
        this.successListener = successListener;
        setRetryPolicy(new DefaultRetryPolicy(10 * 1000, 0, 0));
    }

    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        Response<T> tResponse = null;
        String json;
        try {
            Gson gson = new Gson();
            json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            if (type == null) {
                tResponse = (Response<T>) Response.success(gson.fromJson(json, clazz), HttpHeaderParser.parseCacheHeaders(response));
            } else {
                tResponse = (Response<T>) Response.success(gson.fromJson(json, type), HttpHeaderParser.parseCacheHeaders(response));
            }
        } catch (UnsupportedEncodingException e) {
            Log.e(TAG, "parseNetworkResponse:", e);
            tResponse.error(new ParseError(e));
        } catch (JsonSyntaxException e) {
            Log.e(TAG, "parseNetworkResponse:", e);
            tResponse.error(new ParseError(e));
        } catch (Exception e) {
            Log.e(TAG, "parseNetworkResponse:", e);
            tResponse.error(new ParseError(e));
        }
        return tResponse;
    }


    @Override
    protected Map<String, String> getParams() throws AuthFailureError {
        Hashtable<String, String> params = new Hashtable<String, String>();
        for (RequestParam param : requestParams) {
            params.put(param.getKey(), param.getValue());
        }
        return params;
    }

    public void addRequestParams(RequestParam... param) {
        if (param != null) {
            this.requestParams.addAll(Arrays.asList(param));
        }
    }

    public LinkedList<RequestParam> getRequestParams() {
        return requestParams;
    }

    @Override
    protected void deliverResponse(T response) {
        if (successListener != null) {
            successListener.onResponse(response);
        }
    }

    @Override
    public String getUrl() {
        String urlString = super.getUrl();
        if (this.httpMethod == Method.GET) {
            boolean isFirst = true;
            for (RequestParam p : requestParams) {
                if (isFirst) {
                    isFirst = false;
                    urlString += "?";
                } else {
                    urlString += "&";
                }
                try {
                    urlString += URLEncoder.encode(p.getKey(), "UTF-8");
                    urlString += "=";
                    urlString += URLEncoder.encode(p.getValue(), "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            if (urlString.endsWith("&")) {
                urlString = urlString.substring(0, urlString.length() - 1);
            }
        }
        return urlString;
    }

    public static class RequestBody {
        public final String contentType;
        private final byte[] content;

        public RequestBody(String contentType, byte[] content) {
            this.contentType = contentType;
            this.content = content;
        }
    }
}
